﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Threading.Tasks;

namespace shop.Web.Common
{

    /// <summary>
    /// 全局异常错误日志
    /// </summary>
    public class GlobalExceptionsFilter : IAsyncExceptionFilter  // IExceptionFilter
    {
        private readonly ILogger<GlobalExceptionsFilter> _logger;

        public GlobalExceptionsFilter(ILogger<GlobalExceptionsFilter> logger)
        {
            _logger = logger;
        }


        public async Task OnExceptionAsync(ExceptionContext context)
        {
            var apiResult = new ApiResult
            {
                msg = context.Exception.Message,//错误信息
                code = 410,
            };


            //进行错误日志记录
            var info = await WriteLogInfo(apiResult.msg, context.Exception, context);
            _logger?.LogError(apiResult.msg+ info);

            await Task.CompletedTask;
        }



        /// <summary>
        /// 定义返回格式
        /// </summary>
        /// <param name="throwMsg"></param>
        /// <param name="ex"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task<string> WriteLogInfo(string throwMsg, Exception ex, ExceptionContext context)
        {
            string pr = string.Empty;

            if(context.HttpContext.Request.Method.ToUpper() == "GET")
            {
                pr = context?.HttpContext?.Request?.QueryString.Value;
            }
            else if (context.HttpContext.Request.Method.ToUpper() == "POST")
            {
                pr = await GetExceptionRequestBody(context);
            }

            return string.Format("\r\n【自定义错误】：{0} \r\n【异常类型】：{1} \r\n【异常信息】：{2} \r\n【堆栈调用】：{3}\r\n【入参参数】：{4} \r\n", 
                new object[] 
                { 
                    throwMsg, 
                    ex.GetType().Name, 
                    ex.Message, 
                    ex.StackTrace,
                    pr,
                }
            );
        }


        private async Task<string> GetExceptionRequestBody(ExceptionContext context)
        {
            string requestBody = "";
            if (context != null)
            {
                var request = context?.HttpContext?.Request;
                if (request != null)
                {
                    request.Body.Position = 0;
                    StreamReader stream = new StreamReader(request.Body);
                    //requestBody = stream.ReadToEnd();
                    try
                    {
                        requestBody = await stream.ReadLineAsync() + "\r\n";
                        requestBody += await stream.ReadLineAsync() + "\r\n";
                        requestBody += await stream.ReadLineAsync() + "\r\n";
                    }
                    catch (Exception)
                    {
                    }

                    request.Body.Position = 0;
                }
            }
            return requestBody;
        }

    }



    public class ApiResult
    {
        public string msg { set; get; }

        public int code { set; get; }   


    }




}
